# -*- encoding: utf-8 -*-
"""
@File        : heartbeat_detection_unit.py
@License     : (C)Copyright 2021 LeeRoc (cn) Lipeng
@Modify Time : 2021/7/29 11:20 下午
@Author      : LeeRoc
@Version     : 1.0
@Description : 分布式系统心跳协议的设计

进程 C 依赖于 S, 则一般 S 为 sender, C 为 receiver.

心跳设计关键：（高置信度与低反应时间不可兼得）
    1、通常 sender 的发送周期和 receiver 的检查周期相同, 为 T; timeout 时间一般为 2T
    2、T 越小, 开销越大; T 越大, receiver 检测到故障的延迟也就越大
    3、心跳信息应该包含发送方的标识符; 建议也包含当前负载, 便于客户端做负载均衡
    4、如果 sender 和 receiver 之间有其他消息中转进程, 那么还应该加上 sender 的发送时间, 防止消息在传输过程中堆积而导致假心跳
    5、要在工作线程中发送, 不要单独起一个”心跳线程”, 防止伪心跳（防止工作线程死锁或阻塞时还在发送心跳）
    6、与业务信息用同一个连接, 不要单独用”心跳连接”, 防止伪心跳（如果验证的不是收发业务数据的 TCP 连接畅通则意义不大）

该类设计两个一个是用来检测进程是否存活，一个用来检测端口网络是否通畅
"""

import sys
import socket
import subprocess
import re

sys.path.append('../')

from tool.current_time import current_time

socket.setdefaulttimeout(10)  # 设置默认超时时间


def socket_port_check(ip: str, port: int):
    """
    检测IP端口的状态
    info: print(socket_port_check('0.0.0.0', 22))
          # 2021-08-01 11:46:36 -- 0.0.0.0 : 22 0
            ok
    :param ip:
    :param port:
    """
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        result = s.connect_ex((ip, port))
        if result == 0:
            print(current_time().get_current_time(), '--', ip, ':', port, result)
            return 'ok'
        else:
            print(current_time().get_current_time(), '--', ip, ':', port, result)
            return 'block'
    except Exception as e:
        raise e


def delay_check(ip: str):
    """
    用法
    message = delay_check('0.0.0.0')
    print(message['result'])
    info: bad
    :param ip: ip地址
    :return:
    """
    ping_result = {'result': 'ok'}
    p = subprocess.Popen(
        "ping -c 3 {0} \n".format(ip),
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        shell=True)

    out = p.stdout.read().decode('gbk')
    regIP = r'\d+\.\d+\.\d+\.\d+'
    regLost = r', (\d.*?%) packet loss'
    regAverage = r'= (.*?) ms'

    ip = re.search(regIP, out)
    lost = re.findall(regLost, out)[0]
    reaverage = re.findall(regAverage, out)

    if reaverage:
        average = reaverage[0].split('/')[1]
        ping_result['average'] = float(average)
    if ip:
        ip = ip.group()
        ping_result['ip'] = ip
    if lost:
        lost = lost.split(',')[1].lstrip()
        lost = float(lost.replace('%', ''))
        ping_result['lost'] = lost
    if ping_result['lost'] >= 10:
        # print(f"丢包率为:{ping_result['lost']}")
        ping_result['result'] = 'bad'
    if 'average' in ping_result:
        if ping_result['average'] >= 300:
            # print(f"延时过高,平均延时:{ping_result['average']}")
            ping_result['result'] = f"延时过高{ping_result['average']}"

    return ping_result['result']


def processing_check(pid):
    pass
